<template>
  <div class="minder-editor-container">
    <div class="minder-title" v-show="titleShow">
      <div class="minder-title-name" :style="{'color': titleColor}">{{title}}</div>
      <div class="minder-operation">
        <div style="margin-right: 15px">
          <el-button v-if="historyVersion.metadata.time" @click="cancelPreview" size="mini">取消预览</el-button>
        </div>
        <history-popover
          ref="historyPopover"
          :has-history-version.sync="hasHistoryVersion"
          :history-list-popover-visible.sync="historyListPopoverVisible"
          :history-operation-loading="!loading.closed"
          :saved.sync="saved"
          @viewHistoryFile="viewHistoryFile"
          @recoverySuccess="recoverySuccess"
        >
        </history-popover>
        <div>
          <el-button v-if="!saved" @click="save" size="mini" :loading="saveBtnUpdating">保存</el-button>
        </div>
      </div>
    </div>
    <div class="quickbar">
      <el-tooltip placement="top" effect="light">
        <div><em class="ft icon" title="缩放">
          <svg-icon icon-class="zoom-out"/>
        </em></div>
        <div slot="content" class="minder-editor-slider">
          <el-slider v-model="zoom" :min="10" :max="300" input-size="mini" tooltip-class="slider-tooltip"></el-slider>
        </div>
      </el-tooltip>
      <el-tooltip v-if="!hasReadOnly" placement="top" effect="light">
        <div>
          <em class="ft icon" title="图形">
            <svg-icon icon-class="graph1"/>
          </em>
        </div>
        <div slot="content">
          <ul class="minder-editor-quickul mold" style="margin-bottom: 0;">
            <li @click="execCommand('template', 'default')" title="默认"><span class="default"></span></li>
            <li @click="execCommand('template', 'structure')" title="结构"><span class="structure"></span></li>
            <li @click="execCommand('template', 'filetree')" title="树形"><span class="filetree"></span></li>
            <li @click="execCommand('template', 'right')" title="靠右"><span class="right"></span></li>
            <li @click="execCommand('template', 'fish-bone')" title="鱼骨"><span class="fish-bone"></span></li>
            <li @click="execCommand('template', 'tianpan')" title="天盘"><span class="tianpan"></span></li>
          </ul>
        </div>
      </el-tooltip>
      <el-tooltip v-if="!hasReadOnly" placement="top" effect="light">
        <div>
          <em class="ft icon" title="样式">
            <svg-icon icon-class="clothes"/>
          </em>
        </div>
        <div slot="content">
          <ul class="minder-editor-quickul" style="margin-bottom: 0;">
            <li @click="execCommand('theme', 'fresh-blue')">天空蓝</li>
            <li @click="execCommand('theme', 'wire')">线框</li>
            <li @click="execCommand('theme', 'fish')">鱼骨图</li>
            <li @click="execCommand('theme', 'classic')">脑图经典</li>
            <li @click="execCommand('theme', 'classic-compact')">紧凑经典</li>
            <li @click="execCommand('theme', 'snow')">温柔冷光</li>
            <li @click="execCommand('theme', 'snow-compact')">紧凑冷光</li>
            <li @click="execCommand('theme', 'tianpan')">经典天盘</li>
            <li @click="execCommand('theme', 'tianpan-compact')">紧凑天盘</li>
          </ul>
        </div>
      </el-tooltip>
      <el-tooltip placement="top" effect="light">
        <div>
          <em class="ft icon" title="折叠">
            <svg-icon icon-class="zhankai"/>
          </em>
        </div>
        <div slot="content">
          <ul class="minder-editor-quickul" style="margin-bottom: 0;">
            <li @click="execCommand('ExpandToLevel', 1)">展开到一级节点</li>
            <li @click="execCommand('ExpandToLevel', 2)">展开到二级节点</li>
            <li @click="execCommand('ExpandToLevel', 3)">展开到三级节点</li>
            <li @click="execCommand('ExpandToLevel', 4)">展开到四级节点</li>
            <li @click="execCommand('ExpandToLevel', 5)">展开到五级节点</li>
            <li @click="execCommand('ExpandToLevel', 99)">展开全部节点</li>
          </ul>
        </div>
      </el-tooltip>
      <el-tooltip placement="top" content="居中" effect="light">
        <div @click="minder.execCommand('camera', minder.getRoot(), 600)">
          <em class="ft icon">
            <svg-icon icon-class="Location"/>
          </em>
        </div>
      </el-tooltip>
      <el-tooltip placement="top" content="移动" effect="light">
        <div @click="execCommand('Hand', isHand)">
          <em class="ft icon" :class="{active:isHand}">
            <svg-icon icon-class="cc-hand"/>
          </em>
        </div>
      </el-tooltip>
    </div>
    <div :id="id"></div>
  </div>
</template>


<script>
import {generateMixed} from 'vue-kityminder-ggg/src/utils/index.js';
import 'vue-kityminder-ggg/examples/styles/minder.css';
import JSPDF from 'jspdf';
import api from "@/api/file-api";
import txtApi from "@/api/markdown-api";
import historyApi from "@/api/file-history";
import HistoryPopover from "@/components/HistoryPopover/index.vue";
import {mapState} from "vuex";


export default {
  name: 'my-mind-editor',
  components: {HistoryPopover},
  props: {
    file: {
      type: Object,
      default: function () {
        return {}
      }
    },
    shareId: {
      type: String,
      default: ''
    },
    readOnly: {
      type: Boolean,
      default: false
    },
    id: {
      type: String,
      default: 'minder-component-' + generateMixed(12)
    },
  },
  computed: {
    ...mapState(['message']),
    hasReadOnly() {
      return this.readOnly || this.viewHistory
    },
    titleColor() {
      if (!this.saved) {
        return '#ff8200'
      }
      return ''
    }
  },
  data() {
    return {
      minder: null,
      isHand: false,
      title: this.file.name,
      saveBtnUpdating: false,
      bakValue: '',
      content: null,
      zoom: 100,
      saved: true,
      titleShow: false,
      currentContext: undefined,
      currentTitle: undefined,
      historyVersion: {metadata: {}},
      hasHistoryVersion: false,
      historyListPopoverVisible: false,
      viewHistory: false,
      loading: {
        closed: true
      },
    }
  },
  watch: {
    'file.id': {
      handler(id) {
        if (!id) {
          return
        }
        let request = 'previewText'
        if (!this.$store.state.user.token) {
          request = 'sharePreviewText'
        }
        this.content = null
        api[request]({
          shareId: this.shareId,
          fileId: this.file.id,
          id: this.file.id,
          fileName: this.file.name,
          path: encodeURI(this.file.path),
          username: this.$store.state.user.name,
          content: true,
        }).then((res) => {
          this.file.path = res.data.path
          if (res.data.contentText && res.data.contentText.length > 1) {
            this.content = JSON.parse(res.data.contentText)
          }
          this.init(this.content)
          this.$emit('onReady')
        })
        this.$nextTick(()=> {
          this.$refs.historyPopover.loadHistoryList(this.file.id)
        })
      },
      deep: true,
      immediate: true
    },
    zoom(val) {
      this.execCommand('Zoom', val)
    },
    message(msg) {
      if (msg.event === 'previewSaveAndClose') {
        this.saveAndClose()
      }
    }
  },
  mounted() {
    document.addEventListener('keydown', this.ctrlAndS)
  },
  destroyed() {
    document.removeEventListener('keydown', this.ctrlAndS)
  },
  methods: {
    viewHistoryFile({historyInfo, recovery}) {
      if (!this.saved) {
        this.$message({type: 'info', message: "请先保存当前修改的内容"})
        return
      }
      let loadingInfo = recovery ? '恢复中...' : '加载中...'
      this.loading = this.$message({
        iconClass: 'el-icon-loading',
        type: 'info',
        duration: 0,
        dangerouslyUseHTMLString: true,
        message: `<span>&nbsp;&nbsp;${loadingInfo}</span>`
      })
      historyApi.previewHistoryText({id: historyInfo.id}).then((res) => {
        this.loading.close()

        if (this.historyListPopoverVisible) {
          this.historyListPopoverVisible = false
        }
        if (recovery) {
          this.cancelPreview(null, res.data.contentText)
          this.$message({message: '恢复成功',type: 'success'})
        } else {
          this.currentContext = JSON.stringify(this.content)
          this.currentTitle = this.title
          this.content = JSON.parse(res.data.contentText)
          this.bakValue = res.data.contentText
          this.minder.importJson(this.content)
          this.historyVersion = historyInfo
          this.title = `历史版本：${historyInfo.metadata.time}`
          this.viewHistory = true
          this.setReadOnly()
        }
      }).catch(() => {
        this.loading.close()
      })
    },
    recoverySuccess({historyInfo}) {
      this.viewHistoryFile({historyInfo: historyInfo, recovery: true})
    },
    cancelPreview(event, currentContext) {
      if (!currentContext) {
        currentContext = this.currentContext
      }
      this.historyVersion = {metadata: {}}
      this.content = JSON.parse(currentContext)
      this.bakValue = currentContext
      this.minder.importJson(this.content)
      if (this.currentTitle) {
        this.title = this.currentTitle
      }
      this.viewHistory = false
      this.setReadOnly()
    },
    setReadOnly() {
      window.__minderReadOnly = this.hasReadOnly
      if (this.hasReadOnly === true) {
        this.minder.disable()
        this.minder.execCommand('Hand')
        this.isHand = true
      } else {
        this.minder.enable()
      }
    },
    saveAndClose() {
      this.save()
      this.$emit('onClose')
    },
    ctrlAndS(event) {
      // ctrl + s
      const isMac = navigator.platform.startsWith('Mac');
      const {key, code, keyCode, ctrlKey, metaKey} = event;
      const isCmd = isMac && metaKey || !isMac && ctrlKey;
      if (!isCmd) {
        return;
      }
      const ctrlAndS = key === 's' || code === 'KeyS' || keyCode === 83;
      if (ctrlAndS) {
        this.save()
        event.stopPropagation();
        event.preventDefault();
      }
    },
    execCommand(var1, var2) {
      if (var1 === 'Hand') {
        this.isHand = !var2
      }
      if (this.readOnly === true) {
        this.minder.enable()
        this.$nextTick(() => {
          this.minder.execCommand(var1, var2)
          this.$nextTick(() => {
            this.minder.disable()
            if (this.isHand) {
              this.minder.execCommand('Hand')
            }
          })
        })
      } else {
        this.minder.execCommand(var1, var2)
      }
    },
    exportHandle(n, filename) {
      filename = filename || (this.content.root.data.text || '无标题')
      if (n === 0 || n === 'png') {
        this.minder.exportData('png').then((content) => {
          let element = document.createElement('a')
          element.setAttribute('href', content)
          element.setAttribute('download', filename)
          element.style.display = 'none'
          document.body.appendChild(element)
          element.click()
          document.body.removeChild(element)
        })
      } else if (n === 1 || n === 'pdf') {
        this.minder.exportData('png').then((content) => {
          let doc = new JSPDF()
          doc.addImage(content, 'PNG', 0, 0, 0, 0)
          doc.save(`${filename}.pdf`)
        })
      }
    },
    rendData() {
      this.$nextTick(() => {
        setTimeout(() => {
          if (this.minder !== null) {
            if (this.bakValue === JSON.stringify(this.content)) {
              return
            }
            this.bakValue = JSON.stringify(this.content)
            this.minder.importJson(this.content)
            return
          }
          const Editor = require('./editor')
          this.minder = window.editor = new Editor(document.getElementById(this.id)).minder
          this.bakValue = JSON.stringify(this.content)
          this.titleShow = true
          this.minder.importJson(this.content)
          this.setReadOnly()
          this.minder.on('contentchange', () => this.onContentChange())
        }, 300)
      })
    },
    onContentChange() {
      const newJson = this.minder.exportJson()
      if (this.bakValue === JSON.stringify(newJson)) {
        this.saved = true
        if (this.title === `*${this.file.name}`) {
          this.title = this.file.name
        }
      } else {
        this.content = newJson
        this.saved = false
        this.title = `*${this.file.name}`
      }
      this.$emit('onEdit', this.saved)
    },
    init(newObj) {
      if (typeof newObj !== "object" || newObj === null) {
        newObj = {
          root: newObj,
          theme: "fresh-blue",
          template: "default",
        }
      }
      if (typeof newObj.root !== "object" || newObj.root === null || newObj.root.length === 0) {
        newObj.root = {
          data: {
            id: generateMixed(12),
            text: '默认节点',
          },
          children: []
        }
      }
      if (typeof newObj.theme !== "string") {
        newObj.theme = "fresh-blue"
      }
      if (typeof newObj.template !== "string") {
        newObj.template = "default"
      }
      this.rendData()
    },
    save() {
      if (!this.saved) {
        this.update(JSON.stringify(this.content))
      }
    },
    update(value) {
      this.saveBtnUpdating = true
      txtApi.editMarkdownByPath({
        relativePath: encodeURI(this.file.path + this.file.name),
        userId: this.$store.state.user.userId,
        username: this.$store.state.user.name,
        mountFileId: this.$store.state.user.userId !== this.file.userId ? this.file.id : '',
        contentText: value
      }).then(() => {
        this.saveBtnUpdating = false
        this.saved = true
        this.title = this.file.name
        this.$emit('onEdit', this.saved)
        this.bakValue = value
        this.$refs.historyPopover.loadHistoryList(this.file.id)
      }).catch(() => {
        this.saveBtnUpdating = false
      })
    },
  }
}
</script>
<style lang="scss" scoped>
.basebtn {
  color: #fff;
  background-color: #409eff;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid #dcdfe6;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: 0.1s;
  font-weight: 500;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  padding: 8px 12px;
  font-size: 14px;
  border-radius: 4px;
}

.baseSelect {
  height: 32px;

  option {
    min-height: 1.5em;
  }
}

.quickbar {
  position: fixed;
  left: 20px;
  bottom: 20px;
  height: 34px;
  border-radius: 3px;
  box-shadow: 3px 3px 10px rgba(0, 0, 0, .2);
  background-color: #fff;
  color: #666;
  z-index: 10;
  display: flex;
  padding: 0 6px;
  align-items: center;

  em {
    font-size: 22px;
    width: 34px;
    height: 34px;
    line-height: 34px;
    display: block;
    text-align: center;
    transform: scale(1);
    cursor: pointer;
    padding: 0;
    color: #666666;
    font-style: normal;

    &:hover {
      color: #232323;
    }

    &.active {
      color: #0285d7;
    }

    .svg-icon {
      font-size: 22px;
    }
  }
}
>>>.minder-editor-quickul {
  li {
    list-style: none;
    cursor: pointer;
    padding: 8px 0;

    &:hover {
      color: #0285d7
    }
  }

  &.mold {
    span {
      display: block;
      width: 30px;
      background: url() no-repeat;
      background-size: 300px 24px;
      height: 30px;

      &.default {
        background-position: 0 3px
      }

      &.structure {
        background-position: -30px 3px
      }

      &.filetree {
        background-position: -60px 3px
      }

      &.right {
        background-position: -90px 3px
      }

      &.fish-bone {
        background-position: -120px 3px
      }

      &.tianpan {
        background-position: -150px 3px
      }
    }
  }
}

.minder-editor-slider {
  width: 200px;
  margin: 0 6px;
}

>>>.slider-tooltip {
  background: #5a5e66;
}

.minder-editor-container {
  position: absolute;
  top: 2.5rem;

  .minder-title {
    text-align: center;
    background-color: #fbfbfb;
    z-index: 2001;
    position: absolute;
    top: 0;
    width: 100%;
    height: 40px;
    box-shadow: 0 1px 3px #00000033;

    .minder-title-name {
      line-height: 40px;
    }

    .minder-operation {
      display: flex;
      float: right;
      margin-top: -40px;
      margin-right: 30px;
      line-height: 40px;
    }
  }
}
</style>
